package com.xbongbong.workflow.service.strategy.node.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.domain.entity.ext.OptionalRangeEntity;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.NodeTypeEnum;
import com.xbongbong.paas.enums.TaskTypeEnum;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.pro.thread.ThreadPoolBeanConfig;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.enums.SignTypeEnum;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.UserModel;
import com.xbongbong.workflow.domain.entity.WorkflowEntity;
import com.xbongbong.workflow.domain.entity.WorkflowNodeEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTaskEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTaskNodeEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTransferDataEntity;
import com.xbongbong.workflow.enums.WorkflowNodeTypeEnum;
import com.xbongbong.paas.config.enums.WorkflowTaskLogStatusEnum;
import com.xbongbong.paas.exception.WorkflowException;
import com.xbongbong.workflow.model.WorkflowModel;
import com.xbongbong.workflow.model.WorkflowNodeModel;
import com.xbongbong.workflow.model.WorkflowTaskModel;
import com.xbongbong.workflow.model.WorkflowTaskNodeModel;
import com.xbongbong.workflow.model.WorkflowTransferDataModel;
import com.xbongbong.workflow.pojo.Data;
import com.xbongbong.workflow.pojo.User;
import com.xbongbong.workflow.pojo.WorkflowCreateTaskNodePojo;
import com.xbongbong.workflow.pojo.WorkflowProcessResultPojo;
import com.xbongbong.workflow.pojo.WorkflowTransferPOJO;
import com.xbongbong.workflow.pojo.nodes.CcNode;
import com.xbongbong.workflow.service.strategy.node.AbstractWorkflowApprovalStrategy;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * 抄送节点
 * @author 魏荣杰
 */
@Service
@Slf4j
public class WorkflowNodeCCStrategy extends AbstractWorkflowApprovalStrategy {

    @Resource
    private UserModel userModel;
    @Resource
    private WorkflowTaskModel workflowTaskModel;
    @Resource
    private WorkflowModel workflowModel;
    @Resource
    private ThreadPoolBeanConfig threadPoolBeanConfig;
    @Resource
    private WorkflowTransferDataModel workflowTransferDataModel;
    @Resource
    private WorkflowNodeModel workflowNodeModel;
    @Resource
    private WorkflowTaskNodeModel workflowTaskNodeModel;

    @Override
    public String type() {
        return WorkflowNodeTypeEnum.CC_NODE.getName();
    }

    @Override
    public void before(WorkflowTransferPOJO workflowTransferPOJO) {
        super.before(workflowTransferPOJO);
    }

    @Override
    public WorkflowProcessResultPojo process(WorkflowTransferPOJO workflowTransferPOJO, WorkflowNodeEntity workflowNodeEntity, Long lastNodeId, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo) {
        try {
            WorkflowCreateTaskNodePojo workflowCreateTaskNodePojo = createTaskNode(workflowTransferPOJO, workflowNodeEntity, lastNodeId, saasNeedRedundantAttrPojo);
            if (workflowCreateTaskNodePojo.getIsNeedApproval()) {
                CcNode configData = JSON.parseObject(workflowNodeEntity.getConfigData(), CcNode.class);
                List<OptionalRangeEntity> ccUser = configData.getCcUserList();
                Set<String> nodeTaskUserList = new HashSet<>();
                if (!ccUser.isEmpty()) {
                    // 获取节点人员
                    nodeTaskUserList = getNodeTaskUserList(ccUser, workflowTransferPOJO);
                }
                List<UserEntity> userEntityList = userModel.getByUserIdIn(workflowNodeEntity.getCorpid(), new ArrayList<>(nodeTaskUserList), true);
                List<String> userNameList = new ArrayList<>();
                userEntityList.forEach(userEntity -> userNameList.add(userEntity.getName()));
                String waitCcUserName = StringUtils.join(userNameList, StringConstant.COMMA);

                logger(workflowTransferPOJO, workflowNodeEntity, WorkflowTaskLogStatusEnum.PASS, new WorkflowException(MessageConstant.WORKFLOW_NODE_PAAS_CC, waitCcUserName));
            } else {
                if (workflowCreateTaskNodePojo.getIsWhitoutApproval()) {
                    logger(workflowTransferPOJO, workflowNodeEntity, WorkflowTaskLogStatusEnum.PASS, new WorkflowException(MessageConstant.WORKFLOW_NODE_WITHOUT_APPROVAL));
                }
            }

        } catch (WorkflowException e) {
            logger(workflowTransferPOJO, workflowNodeEntity, WorkflowTaskLogStatusEnum.SUSPEND, e);
            return new WorkflowProcessResultPojo(false, false, true);
        }
        return new WorkflowProcessResultPojo(true, false);
    }

    @Override
    public void after(WorkflowTransferPOJO workflowTransferPOJO, WorkflowNodeEntity workflowNodeEntity) {
        super.after(workflowTransferPOJO, workflowNodeEntity);

    }

    @Override
    public void check() {
        super.check();
    }

    private WorkflowCreateTaskNodePojo createTaskNode(WorkflowTransferPOJO workflowTransferPOJO, WorkflowNodeEntity nodeEntity, Long lastNodeId, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo) throws WorkflowException {
        try {
            // 处理抄送节点在审批节点前，且设置了无需审批人的情况，不生成审批数据，但是生成节点日志
            WorkflowEntity workflowEntity = workflowModel.getByKey(nodeEntity.getWorkflowId(), nodeEntity.getCorpid());
            if (isNoNeedApproval(workflowTransferPOJO.getUser(), workflowEntity.getRolesWithoutApprove(), nodeEntity.getCorpid())) {
                return new WorkflowCreateTaskNodePojo(false, true);
            }

            CcNode configData = JSON.parseObject(nodeEntity.getConfigData(), CcNode.class);
            List<OptionalRangeEntity> ccUser = configData.getCcUserList();
            if (!ccUser.isEmpty()) {
                // 获取节点人员
                Set<String> nodeTaskUserList = getNodeTaskUserList(ccUser, workflowTransferPOJO);
                if (Objects.isNull(workflowTransferPOJO.getTaskId())) {
                    // 特殊情况：没有设置审批节点，直接设置抄送节点的情况，需要生成task任务
                    createTaskNodeForCc(workflowTransferPOJO, nodeEntity);

                    WorkflowTransferDataEntity workflowTransferDataEntity = new WorkflowTransferDataEntity();
                    workflowTransferDataEntity.setData(JSON.parseObject(JSON.toJSONString(workflowTransferPOJO, SerializerFeature.DisableCircularReferenceDetect)));
                    if (Objects.nonNull(saasNeedRedundantAttrPojo)) {
                        workflowTransferDataEntity.setSaasNeedPojo(JSON.parseObject(JSON.toJSONString(saasNeedRedundantAttrPojo, SerializerFeature.DisableCircularReferenceDetect)));
                    }
                    workflowTransferDataEntity.setWorkflowId(nodeEntity.getWorkflowId());
                    workflowTransferDataEntity.setCorpid(workflowTransferPOJO.getCorpid());
                    workflowTransferDataEntity.setTaskId(workflowTransferPOJO.getTaskId());
                    workflowTransferDataEntity.setLogId(workflowTransferPOJO.getLogId());
                    workflowTransferDataEntity.setFormId(workflowTransferPOJO.getData().getFormId());
                    workflowTransferDataEntity.setSaasMark(workflowTransferPOJO.getData().getSaasMark());
                    workflowTransferDataEntity.setBusinessType(workflowTransferPOJO.getData().getBusinessType());
                    workflowTransferDataEntity.setOperate(workflowTransferPOJO.getOperate());
                    workflowTransferDataEntity.setDataId(workflowTransferPOJO.getData().getId());
                    workflowTransferDataEntity.setDel(DelEnum.NORMAL.getDel());
                    workflowTransferDataModel.insert(workflowTransferDataEntity);
                }
                createApprovalNode(nodeTaskUserList, workflowTransferPOJO, nodeEntity, lastNodeId, TaskTypeEnum.CC);
            }
        } catch (Exception e) {
            throw new WorkflowException("com.xbongbong.workflow.service.strategy.node.impl.WorkflowNodeCCStrategy.createTaskNode ", e);
        }
        return new WorkflowCreateTaskNodePojo(true, false);
    }

    private void createTaskNodeForCc(WorkflowTransferPOJO workflowTransferPOJO, WorkflowNodeEntity nodeEntity) {
        String corpid = nodeEntity.getCorpid();
        Data data = workflowTransferPOJO.getData();
        User user = workflowTransferPOJO.getUser();
        WorkflowEntity workflowEntity = workflowModel.getByKey(nodeEntity.getWorkflowId(), corpid);

        long now = DateTimeUtil.getInt();
        WorkflowTaskEntity workflowTaskEntity = new WorkflowTaskEntity();
        workflowTaskEntity.setCorpid(corpid);
        workflowTaskEntity.setAppId(data.getAppId());
        workflowTaskEntity.setFormId(data.getFormId());
        workflowTaskEntity.setMenuId(data.getMenuId());
        workflowTaskEntity.setWorkflowId(workflowEntity.getId());
        workflowTaskEntity.setDataId(data.getId());
        workflowTaskEntity.setSaasMark(data.getSaasMark());
        workflowTaskEntity.setBusinessType(data.getBusinessType());
        workflowTaskEntity.setFlowStatus(FlowStatusEnum.APPROVAL_PENDING.getType());
        workflowTaskEntity.setCreatorId(user.getUserId());
        workflowTaskEntity.setAddTime(now);
        workflowTaskEntity.setUpdateTime(now);
        workflowTaskEntity.setDel(DelEnum.NORMAL.getDel());
//            workflowTaskEntity.setDingtalkProcessInstanceId();

        Long insert = workflowTaskModel.insert(workflowTaskEntity);

        // 绑定审批task
        workflowTransferPOJO.setTaskId(workflowTaskEntity.getId());

        Runnable runnable = () -> createDingtalkInstance(workflowTransferPOJO, nodeEntity, insert);

        threadPoolBeanConfig.dingtalkTodo().execute(runnable);

        // 创建初始审批记录节点
        WorkflowTaskNodeEntity workflowTaskNodeEntity = new WorkflowTaskNodeEntity();
        workflowTaskNodeEntity.setCorpid(nodeEntity.getCorpid());
        workflowTaskNodeEntity.setAppId(nodeEntity.getAppId());
        workflowTaskNodeEntity.setFormId(nodeEntity.getFormId());
        workflowTaskNodeEntity.setMenuId(nodeEntity.getMenuId());
        workflowTaskNodeEntity.setSaasMark(nodeEntity.getSaasMark());
        workflowTaskNodeEntity.setBusinessType(nodeEntity.getBusinessType());
        workflowTaskNodeEntity.setWorkflowId(nodeEntity.getWorkflowId());
        workflowTaskNodeEntity.setTaskId(workflowTransferPOJO.getTaskId());

        workflowTaskNodeEntity.setUserId(user.getUserId());
        workflowTaskNodeEntity.setDataId(workflowTransferPOJO.getData().getId());
        workflowTaskNodeEntity.setTaskType(TaskTypeEnum.COMMIT.getType());
        workflowTaskNodeEntity.setSignType(SignTypeEnum.ORSIGN.getValue());
        workflowTaskNodeEntity.setNodeType(NodeTypeEnum.START_PROCESS_NODE.getNodeType());
        workflowTaskNodeEntity.setLastNodeId(0L);

        // 初始节点，审批提交节点id用触发节点id
        WorkflowNodeEntity startNode = workflowNodeModel.getByUId(nodeEntity.getWorkflowId(), corpid, "startNode");
        workflowTaskNodeEntity.setWorkflowNodeId(startNode.getId());
        workflowTaskNodeEntity.setOpinion("");
        workflowTaskNodeEntity.setImages("");
        workflowTaskNodeEntity.setAttachment("");
        workflowTaskNodeEntity.setTransferUserId("");
        workflowTaskNodeEntity.setRevokeUserId("");
        workflowTaskNodeEntity.setBackspaceNode(0L);
        workflowTaskNodeEntity.setIsRead(0);
        workflowTaskNodeEntity.setAddTime(now);
        workflowTaskNodeEntity.setUpdateTime(now);
        workflowTaskNodeEntity.setDel(DelEnum.NORMAL.getDel());
        workflowTaskNodeEntity.setSerialNo(data.getData().getString("serialNo") == null ? "" : data.getData().getString("serialNo"));
        workflowTaskNodeModel.insert(workflowTaskNodeEntity);

    }

    @Override
    public void logger(WorkflowTransferPOJO workflowTransferPOJO, WorkflowNodeEntity nodeEntity, WorkflowTaskLogStatusEnum workflowTaskLogStatusEnum, WorkflowException workflowException) {
        super.logger(workflowTransferPOJO, nodeEntity, workflowTaskLogStatusEnum, workflowException);
    }


}
